﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using RAP.Framework.Libary.Utils.Extension;
using RAP.Framework.Libary.Utils.Interfaces;

namespace RAP.Framework.Libary.Utils
{
  /// <summary>
  /// IDictionary对象扩展
  /// </summary>
  public static partial class Extensions
  {
    #region IDictionary扩展

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public static T Add<T>(this IDictionary obj, string key, T value)
    {
      obj.Add(key, value);
      return value;
    }

    /// <summary>
    /// 将当前键值对象的值复制到目标键值对象中，如果目标键值对象为null，则创建一个新的键值对象
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="target"></param>
    /// <param name="createFun"></param>
    /// <returns></returns>
    public static IDictionary ToDictionary(this IDictionary obj, IDictionary target = null, Func<IDictionary> createFun = null)
    {
      if (target == null)
      {
        if (createFun != null)
        {
          target = createFun();
        }
        else
        {
          target = new ListDictionary();
        }
      }
      obj.CopyTo(target);
      return target;
    }

    /// <summary>
    /// 对指定的IDictionary对象指定表达式赋值，且以“.”域分割层级赋值，比如：obj.SetDictionaryValue("A.B.C", 1) 等价于 obj["A"]["B"]["C"] = 1
    /// </summary>
    /// <param name="target"></param>
    /// <param name="expression"></param>
    /// <param name="value"></param>
    public static void SetDictionaryValue(this IDictionary target, string expression, object value)
    {
      IList exps = new List<string>(expression.Split('.'));
      string lastKey = exps.Pop<string>();
      foreach (string exp in exps)
      {
        target = target.ToDictionaryValue(exp);
      }
      target[lastKey] = value;
    }

    /// <summary>
    /// 移除指定的键（A.B.C多层结构）
    /// </summary>
    /// <param name="target"></param>
    /// <param name="expression"></param>
    public static bool RemoveKey(this IDictionary target, string expression)
    {
      IList exps = new List<string>(expression.Split('.'));
      string lastKey = exps.Pop<string>();
      foreach (string exp in exps)
      {
        target = target.ToDictionary(exp);
        if (target == null)
        {
          return false;
        }
      }
      target.Remove(lastKey);
      return true;
    }

    /// <summary>
    /// 处理指定键的值的Sql注入
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="type"></param>
    public static void ToSql(this IDictionary obj, object key, ConvertableTypes type = ConvertableTypes.String)
    {
      switch (type)
      {
        case ConvertableTypes.String:
          obj[key] = obj.ToString(key).ProcessSqlInject();
          break;

        case ConvertableTypes.StringList:
          IList list = obj.ToList(key);
          for (int i = 0; i < list.Count; i++)
          {
            list[i] = list[i].ToString().ProcessSqlInject();
          }
          break;
      }
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public static IDictionary Set(this IDictionary obj, object key, object value)
    {
      if (obj == null)
      {
        return null;
      }
      obj.Add(key, value);
      return obj;
    }

    #region ToString

    /// <summary>
    /// 按指定的字符串格式格式化指定Key的值
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="format"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <param name="formatParams">其他格式化参数</param>
    /// <returns></returns>
    public static string Format(this IDictionary obj, string format, string key, string defaultValue = null, params object[] formatParams)
    {
      string value = obj.ToString(key, defaultValue);
      ArrayList paramObjs = new ArrayList();
      paramObjs.Add(value);
      if (formatParams != null)
      {
        paramObjs.AddRange(formatParams);
      }
      return string.Format(format, paramObjs.ToArray());
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="getDefaultValue"></param>
    /// <returns></returns>
    public static string ToString(this IDictionary obj, string key, Func<string> getDefaultValue)
    {
      return obj.ToString(key).IsNullOrEmptyValue(getDefaultValue);
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static string ToString(this IDictionary obj, object key, string defaultValue = null)
    {
      object value;
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      value = obj[key];
      if (value == null)
      {
        return defaultValue;
      }
      return value.ToString();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static bool IsNullOrEmpty(this IDictionary obj, object key)
    {
      return (obj == null || key == null) || !obj.Contains(key) || obj[key].IsNullOrEmpty();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static bool IsNotNullOrEmpty(this IDictionary obj, object key)
    {
      return !obj.IsNullOrEmpty(key);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="options"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static Regex ToRegex(this IDictionary obj, object key
      , RegexOptions options = RegexOptions.Compiled | RegexOptions.Compiled | RegexOptions.IgnoreCase
      , Regex defaultValue = null)
    {
      object value;
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      value = obj[key];
      if (value.IsNullOrEmpty())
      {
        return defaultValue;
      }
      if (value is Regex)
      {
        return value as Regex;
      }
      return new Regex(value.ToString());
    }

    #endregion ToString

    /// <summary>
    /// 将指定key的值转换成指定类型的数据（DateTime、Int32、String、Double）
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="type"></param>
    public static IDictionary ConvertTo(this IDictionary obj, object key, ConvertableTypes type = ConvertableTypes.String)
    {
      switch (type)
      {
        case ConvertableTypes.DateTime:
        case ConvertableTypes.Date:
          obj.ConvertToDateTime(key);
          break;

        case ConvertableTypes.Int32:
        case ConvertableTypes.Int:
          obj.ConvertToInt32(key);
          break;

        case ConvertableTypes.Number:
        case ConvertableTypes.Double:
          obj.ConvertToDouble(key);
          break;

        case ConvertableTypes.Int32List:
          obj.ConvertToInt32Array(key);
          break;

        case ConvertableTypes.StringList:
          obj.ConvertToStringArray(key);
          break;

        case ConvertableTypes.Dictionary:
          obj.ConvertToObject(key);
          break;

        case ConvertableTypes.String:
        default:
          obj.ConvertToString(key);
          break;
      }
      return obj;
    }

    /// <summary>
    /// 将指定key的值转换成日期类型
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    public static IDictionary ConvertToDateTime(this IDictionary obj, object key)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return obj;
      }
      obj[key] = obj.ToDateTime(key);
      return obj;
    }

    /// <summary>
    /// 将指定key的值转换成Int32类型
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    public static IDictionary ConvertToInt32(this IDictionary obj, object key)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return obj;
      }
      obj[key] = obj.ToInt32(key);
      return obj;
    }

    /// <summary>
    /// 将指定key的值转换成Int32类型的数组
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    public static IDictionary ConvertToInt32Array(this IDictionary obj, object key)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return obj;
      }
      obj[key] = obj.ToIntArray(key);
      return obj;
    }

    /// <summary>
    /// 将指定key的值转换成String类型的数组
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    public static IDictionary ConvertToStringArray(this IDictionary obj, object key)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return obj;
      }
      obj[key] = obj.ToStringArray(key);
      return obj;
    }

    /// <summary>
    /// 将指定key的值转换成Double类型
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    public static IDictionary ConvertToDouble(this IDictionary obj, object key)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return obj;
      }
      obj[key] = obj.ToDouble(key);
      return obj;
    }

    /// <summary>
    /// 将指定key的值转换成String类型
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    public static IDictionary ConvertToString(this IDictionary obj, object key)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return obj;
      }
      obj[key] = obj.ToString(key);
      return obj;
    }

    /// <summary>
    /// 将指定key的值转换成键值类型（只能是字符串或键值对象能转换）
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    public static IDictionary ConvertToObject(this IDictionary obj, object key)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return obj;
      }
      var keys = key.ToString().Split(',');
      obj.ConvertToObject(keys);
      return obj;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="keys"></param>
    public static IDictionary ConvertToObject(this IDictionary obj, params string[] keys)
    {
      if (obj == null || keys.IsNullOrEmpty())
      {
        return obj;
      }
      foreach (var key in keys)
      {
        var value = obj[key];
        if (value is string && value != null)
        {
          obj[key] = value.ToString().Eval();
          continue;
        }
      }
      return obj;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    /// <param name="obj"></param>
    /// <param name="fun"></param>
    /// <param name="keys"></param>
    public static IDictionary ConvertToObject<T>(this IDictionary obj, Func<T, object> fun, params string[] keys)
    {
      if (obj == null || keys.IsNullOrEmpty())
      {
        return obj;
      }
      foreach (var key in keys)
      {
        var value = obj[key];
        obj[key] = fun((T)value);
      }
      return obj;
    }

    /// <summary>
    /// 比较指定IDictionary中的键值是否与被比较的键值相等
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="compare"></param>
    /// <returns></returns>
    public static bool IsEquals(this IDictionary obj, IDictionary compare)
    {
      if (compare == null)
      {
        return false;
      }
      foreach (DictionaryEntry ety in compare)
      {
        if (obj[ety.Key] != null)
        {
          if (!obj[ety.Key].IsEquals(ety.Value))
          {
            return false;
          }
        }
        else
        {
          if (ety.Value != null)
          {
            if (!ety.Value.IsEquals(obj[ety.Key]))
            {
              return false;
            }
          }
        }
      }
      return true;
    }


    /// <summary>
    /// 复制键值对象的值到目标键值对象
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="obj"></param>
    /// <param name="dest"></param>
    /// <param name="copyType"></param>
    /// <param name="propertList"></param>
    /// <returns></returns>
    public static IDictionary<TKey, TValue> CopyTo<TKey, TValue>(this IDictionary<TKey, TValue> obj, IDictionary<TKey, TValue> dest, DictionaryCopyTypes copyType = DictionaryCopyTypes.All, object propertList = null)
    {
      if (obj != null)
      {
        Func<TKey, bool> checkCopy = null;
        switch (copyType)
        {
          case DictionaryCopyTypes.All:
            checkCopy = (key) => true;
            break;

          case DictionaryCopyTypes.NotExists:
            checkCopy = (key) => !dest.ContainsKey(key);
            break;

          case DictionaryCopyTypes.Exists:
            checkCopy = (key) => dest.ContainsKey(key);
            break;
        }
        if (propertList.IsNullOrEmpty())
        {
          foreach (KeyValuePair<TKey, TValue> pair in obj)
          {
            var key = pair.Key;
            if (checkCopy(key))
            {
              dest[key] = pair.Value;
            }
          }
        }
        else
        {
          if (propertList is string)
          {
            propertList = propertList.ToString().Split(',');
          }
          foreach (TKey key in (propertList as IEnumerable))
          {
            if (checkCopy(key))
            {
              dest[key] = obj[key];
            }
          }
        }
      }
      return dest;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="obj"></param>
    /// <param name="createDest"></param>
    /// <param name="copyType"></param>
    /// <param name="propertList"></param>
    /// <returns></returns>
    public static IDictionary<TKey, TValue> CopyTo<TKey, TValue>(this IDictionary<TKey, TValue> obj, Func<IDictionary<TKey, TValue>> createDest, DictionaryCopyTypes copyType = DictionaryCopyTypes.All, object propertList = null)
    {
      return obj.CopyTo(createDest(), copyType, propertList);
    }

    /// <summary>
    /// 复制键值对象的值到目标键值对象
    /// </summary>
    /// <param name="srcObj"></param>
    /// <param name="dest"></param>
    /// <param name="copyType">复制方式（0：直接复制，1：复制目标字典不存在的键，2：复制目标存在的键）</param>
    public static IDictionary CopyTo(this IDictionary srcObj, IDictionary dest, DictionaryCopyTypes copyType = DictionaryCopyTypes.All, Action<IDictionary, IDictionary, object, object> copyValue = null)
    {
      if (srcObj != null && dest != null)
      {
        Func<object, bool> checkCopy = null;
        switch (copyType)
        {
          case DictionaryCopyTypes.All:
            checkCopy = (key) => true;
            break;

          case DictionaryCopyTypes.NotExists:
            checkCopy = (key) => !dest.Contains(key);
            break;

          case DictionaryCopyTypes.Exists:
            checkCopy = (key) => dest.Contains(key);
            break;
        }
        if (copyValue == null)
        {
          copyValue = (srcDict, destDict, srcKey, srcValue) =>
          {
            destDict[srcKey] = srcValue;
          };
        }
        foreach (DictionaryEntry ety in srcObj)
        {
          if (checkCopy(ety.Key))
          {
            copyValue(srcObj, dest, ety.Key, ety.Value);
          }
        }
      }
      return dest;
    }

    public static IKeyValuePair CopyTo(this IDictionary srcObj, IKeyValuePair dest, DictionaryCopyTypes copyType = DictionaryCopyTypes.All, Action<IDictionary, IKeyValuePair, object, object> copyValue = null)
    {
      if (srcObj != null && dest != null)
      {
        Func<object, bool> checkCopy = null;
        switch (copyType)
        {
          case DictionaryCopyTypes.All:
            checkCopy = (key) => true;
            break;

          case DictionaryCopyTypes.NotExists:
            checkCopy = (key) => !dest.Contains(key);
            break;

          case DictionaryCopyTypes.Exists:
            checkCopy = (key) => dest.Contains(key);
            break;
        }
        if (copyValue == null)
        {
          copyValue = (srcDict, destDict, srcKey, srcValue) =>
          {
            destDict[srcKey] = srcValue;
          };
        }
        foreach (DictionaryEntry ety in srcObj)
        {
          if (checkCopy(ety.Key))
          {
            copyValue(srcObj, dest, ety.Key, ety.Value);
          }
        }
      }
      return dest;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="targetObj"></param>
    /// <returns></returns>
    public static T Clone<T>(this IDictionary obj, T targetObj)
    {
      return IDictionaryClone<IDictionary, T>.Clone(obj, targetObj);
    }

    /// <summary>
    /// 将指定键的值复制给指定的IDictionary对象
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="dest"></param>
    /// <param name="keys"></param>
    /// <returns></returns>
    public static IDictionary CopyTo(this IDictionary obj, IDictionary dest, params string[] keys)
    {
      if (obj != null && dest != null)
      {
        foreach (var key in keys)
        {
          dest[key] = obj[key];
        }
      }
      return dest;
    }

    /// <summary>
    /// 将键值对象的值复制到对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="data"></param>
    /// <param name="target"></param>
    /// <returns></returns>
    public static T CopyToObject<T>(this IDictionary data, T target)
    {
      if (data == null)
      {
        return target;
      }
      foreach (DictionaryEntry ety in data)
      {
        target.SetValue(ety.Key.ToString(), ety.Value);
      }
      return target;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dict"></param>
    /// <param name="dest"></param>
    /// <param name="keys"></param>
    /// <param name="funGetValue"></param>
    /// <returns></returns>
    public static T CopyToObject<T>(this IDictionary dict, T dest, ICollection keys = null, Func<string, object, object> funGetValue = null)
    {
      if (keys == null)
      {
        keys = dict.Keys;
      }
      foreach (string key in keys)
      {
        dest.SetValue(key, funGetValue != null ? funGetValue(key, dict[key]) : dict[key]);
      }
      return dest;
    }

    /// <summary>
    /// 将指定键的值转换层数组
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static IList<T> ToArray<T>(this IDictionary obj, string key)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return null;
      }
      IList list;
      List<T> result = new List<T>();

      list = obj[key] as IList;
      if (list == null)
      {
        return null;
      }
      foreach (object value in list)
      {
        if (value != null)
        {
          result.Add(value.ToString().Eval());
        }
      }
      return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="ignoreNullValue"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static object[] ToObjectArray(this IDictionary obj, object key, bool ignoreNullValue = true, object[] defaultValue = null)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      IList list;
      List<object> result = new List<object>();
      list = obj[key] as IList;
      if (list == null)
      {
        return defaultValue;
      }
      foreach (object value in list)
      {
        if (ignoreNullValue && value == null)
        {
          continue;
        }
        result.Add(value);
      }
      return result.ToArray();
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static IList<int> ToIntArray(this IDictionary obj, object key)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return null;
      }
      IList list;
      List<int> result = new List<int>();

      list = obj[key] as IList;
      if (list == null)
      {
        return null;
      }
      foreach (object value in list)
      {
        if (value != null)
        {
          result.Add(value.ToInt32Value());
        }
      }
      return result;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static IList<string> ToStringArray(this IDictionary obj, object key)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return null;
      }
      IList list;
      List<string> result = new List<string>();

      list = obj[key] as IList;
      if (list == null)
      {
        return null;
      }
      foreach (object value in list)
      {
        if (value != null)
        {
          result.Add(value.ToString());
        }
      }
      return result;
    }

    #region ToInt32

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static int ToInt32(this IDictionary obj, object key, int defaultValue = 0)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      return obj[key].ToInt32Value(defaultValue);
    }
    #endregion ToInt32


    /// <summary>
    /// 将指定key的属性加上一个整数字并返回计算后的数字
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="addValue"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static int AddInt32(this IDictionary obj, object key, int addValue = 1, int defaultValue = 0)
    {
      if ((obj == null || key == null))
      {
        return defaultValue;
      }
      int value = obj.ToInt32(key) + addValue;
      obj[key] = value;
      return value;
    }


    /// <summary>
    /// 将指定key的属性加上一个浮点数并返回计算后的数字
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="addValue"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static float AddFloat(this IDictionary obj, object key, float addValue = 1, float defaultValue = 0)
    {
      if ((obj == null || key == null))
      {
        return defaultValue;
      }
      float value = obj.ToSingle(key) + addValue;
      obj[key] = value;
      return value;
    }

    #region ToNaturalNumber

    /// <summary>
    /// 将指定key的值转换成自然数（1、2、3、4、5、6、7、8、9、10……），如果小于等于0，则返回defaultValue
    /// </summary>
    /// <returns></returns>
    public static int ToNaturalNumber(this IDictionary obj, object key, int defaultValue = 1)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      int value = obj[key].ToInt32Value(defaultValue);
      value = value > 0 ? value : defaultValue;
      return value;
    }
    #endregion ToNaturalNumber

    #region ToInt64

    /// <summary>
    /// 将指定键值的值对象转换成Int64类型，如果指定键不存在或值为空，则返回defaultValue
    /// </summary>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static long ToInt64(this IDictionary obj, object key, long defaultValue = 0)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      return obj[key].ToInt64Value(defaultValue);
    }
    #endregion ToInt64

    #region ToDecimal

    /// <summary>
    /// 将指定键值的值对象转换成Decimal类型，如果指定键不存在或值为空，则返回defaultValue
    /// </summary>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static decimal ToDecimal(this IDictionary obj, object key, decimal defaultValue = 0)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      return obj[key].ToDecimalValue(defaultValue);
    }
    #endregion ToDecimal

    #region ToSingle

    /// <summary>
    /// 将指定键值的值对象转换成Single类型，如果指定键不存在或值为空，则返回defaultValue
    /// </summary>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static float ToSingle(this IDictionary obj, object key, float defaultValue = 0.0f)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      return obj[key].ToFloatValue(defaultValue);
    }
    #endregion ToSingle

    #region ToDouble

    /// <summary>
    /// 将指定键值的值对象转换成Double类型，如果指定键不存在或值为空，则返回defaultValue
    /// </summary>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static double ToDouble(this IDictionary obj, object key, double defaultValue = 0.0d)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      return obj[key].ToDoubleValue(defaultValue);
    }
    #endregion ToDouble

    #region ToDateTime

    /// <summary>
    /// 将指定键值的值对象转换成DateTime类型，如果指定键不存在或值为空，则返回defaultValue
    /// </summary>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static DateTime? ToDateTime(this IDictionary obj, object key, DateTime? defaultValue = null)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      return obj[key].ToDateTimeValue(defaultValue);
    }

    #endregion ToDateTime

    #region ToEnumValue
    /// <summary>
    /// 扩展IDictionary的ToEnumValue方法，将指定属性转换成指定枚举值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static T ToEnumValue<T>(this IDictionary obj, object key, T defaultValue = default(T))
    {
      if (!obj.Contains(key))
      {
        return defaultValue;
      }
      string value = obj.ToString(key);
      if (key.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return value.ToEnumValue<T>(defaultValue);
    }
    #endregion ToEnumValue

    #region ClearAll
    /// <summary>
    /// 清空字典对象
    /// </summary>
    /// <param name="obj"></param>
    public static void ClearAll(this IDictionary obj)
    {
      foreach (object o in obj.Values)
      {
        IDictionary dict = o as IDictionary;
        if (dict != null)
        {
          dict.ClearAll();
        }
      }
      obj.Clear();
    }
    #endregion ClearAll

    #region ToObject

    /// <summary>
    /// 将指定键值的值对象转换成指定T类型，如果指定键不存在或值为空，则返回null
    /// </summary>
    /// <param name="obj">键值对象</param>
    /// <param name="key">键</param>
    /// <param name="defaultValue">默认值</param>
    /// <returns></returns>
    public static T ToObject<T>(this IDictionary obj, object key, T defaultValue = (default(T)))
    {
      return obj.ToObject<T>(key, () => defaultValue);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="obj">键值对象</param>
    /// <param name="key">键</param>
    /// <param name="func">获取默认值的函数</param>
    /// <returns></returns>
    public static T ToObject<T>(this IDictionary obj, object key, Func<T> func)
    {
      object value;
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return func();
      }
      value = obj[key];
      try
      {
        return (T)value;
      }
      catch { }
      return func();
    }

    public static object ToObject(this IDictionary obj, Type targetType)
    {
      var target = targetType.CreateInstance<object>();
      return obj.CopyToObject<object>(target);
    }

    #endregion ToObject

    #region ParseToList
    /// <summary>
    /// 将指定键的值包装成集合对象返回，如果值本身是集合，则直接返回，否则新建一个集合将值包装后返回
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static IList ParseToList(this IDictionary obj, object key)
    {
      IList result = null;
      object value = obj[key];
      if (value == null)
      {
        return null;
      }
      if (value is IList)
      {
        return value as IList;
      }
      result = new ArrayList();
      result.Add(value);
      return result;
    }
    #endregion ParseToList

    #region ToBoolean
    /// <summary>
    /// 将指定键值的值对象转换成Boolean类型，如果指定键不存在或值为空，则返回defaultValue
    /// </summary>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static bool ToBoolean(this IDictionary obj, object key, bool defaultValue = false)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      return obj[key].ToBooleanValue(defaultValue);
    }

    #endregion ToBoolean

    #region ToDictionary
    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static IDictionary ToDictionary(this IDictionary obj, object key)
    {
      return obj.ToDictionary(key, null);
    }
    #endregion ToDictionary

    /// <summary>
    /// 将指定的键对应的值转换成IDictionary对象，如果值不存在，则根据createfun创建一个值，如果createfun为空，则默认新建一个IDictionary
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="createfun">自定义的值创建函数</param>
    /// <returns>IDictionary</returns>
    public static IDictionary ToDictionaryValue(this IDictionary obj, object key, Func<object, object, IDictionary> createfun = null)
    {
      IDictionary value = obj.ToDictionary(key);
      if (value == null)
      {
        if (createfun == null)
        {
          obj[key] = value = new ListDictionary();
        }
        else
        {
          obj[key] = value = createfun(obj, key);
        }
      }
      return value;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static IDictionary ToDictionary(this IDictionary obj, object key, IDictionary defaultValue)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      object value = obj[key];
      if (value == null)
      {
        return defaultValue;
      }
      if (value is IDictionary)
      {
        return value as IDictionary;
      }
      if (value is string)
      {
        return value.ToString().ToDictionary();
      }
      return null;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static IList ToList(this IDictionary obj, object key, IList defaultValue = null)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue;
      }
      object value = obj[key];
      if (value == null)
      {
        return defaultValue;
      }
      if (value is IList)
      {
        return value as IList;
      }
      if (value is string)
      {
        return value.ToString().ToList();
      }
      return defaultValue;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static IList ToList(this IDictionary obj, object key, Func<IList> defaultValueFunc)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValueFunc();
      }
      object value = obj[key];
      if (value == null)
      {
        return defaultValueFunc();
      }
      if (value is IList)
      {
        return value as IList;
      }
      try
      {
        if (value is string)
        {
          return value.ToString().ToList();
        }
      }
      catch
      {
      }
      return defaultValueFunc();
    }

    /// <summary>
    /// 获取字典对象的第一个值
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static object First(this IDictionary obj)
    {
      return obj.Values.FirstItem();
    }


    #region EvalJSON

    /// <summary>
    /// 将指定键值的值对象按JSON协议转换成键值类型，如果指定键不存在或值为空，则返回null
    /// </summary>
    /// <param name="obj">字典对象</param>
    /// <typeparam name="T"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public static IDictionary parse(this IDictionary obj, object key)
    {
      try
      {
        return obj.ToString(key).ToDictionary();
      }
      catch { }
      return null;
    }

    #endregion EvalJSON

    #region ToJSON

    /// <summary>
    /// 将指定键值的值对象按JSON协议转换成JSON字符串
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string ToJSON(this IDictionary obj, object key)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return null;
      }
      return obj[key].ToJSON();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string ToFileSize(this IDictionary obj, object key)
    {
      return obj.ToInt32(key).ToFileSize();
    }

    #endregion ToJSON

    /// <summary>
    /// 将指定key的值转换成日期类型并按长时间格式转化成字符串
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="format"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static string ToDateTimeString(this IDictionary obj, object key, Func<string> defaultValue = null)
    {
      return obj.ToDateString(key, "yyyy-MM-dd HH:mm", defaultValue);
    }

    /// <summary>
    /// 将指定key的值转换成日期类型并按指定的format格式转化成字符串
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="format"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static string ToDateString(this IDictionary obj, object key, string format = "yyyy-MM-dd", Func<string> defaultValue = null)
    {
      if ((obj == null || key == null) || !obj.Contains(key))
      {
        return defaultValue != null ? defaultValue() : null;
      }
      DateTime? dateTime = obj.ToDateTime(key);
      if (!dateTime.HasValue)
      {
        return defaultValue != null ? defaultValue() : null;
      }
      return dateTime.Value.ToString(format);
    }

    /// <summary>
    /// 循环键值对象的每一个键值对
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="func"></param>
    /// <returns>返回循环次数</returns>
    public static int Each(this IDictionary obj, Func<DictionaryEntry, bool> func)
    {
      if (obj == null)
      {
        return 0;
      }
      int counter = 0;
      if (obj.IsNotNullOrEmpty())
      {
        foreach (DictionaryEntry ety in obj)
        {
          if (!func(ety))
          {
            break;
          }
          counter++;
        }
      }
      return counter;
    }

    public static int Each(this IDictionary obj, Action<DictionaryEntry> action)
    {
      return obj.Each(item =>
     {
       action(item);
       return true;
     });
    }

    #endregion IDictionary扩展

    #region IDictionary<string, object>扩展
    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static string ToString(this IDictionary<string, object> obj, string key, string defaultValue = null)
    {
      object value;
      if ((obj == null || key == null) || !obj.ContainsKey(key))
      {
        return defaultValue;
      }
      value = obj[key];
      if (value == null)
      {
        return defaultValue;
      }
      if (string.IsNullOrEmpty(value.ToString()))
      {
        return defaultValue;
      }
      return value.ToString();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static int ToInt32(this IDictionary<string, object> obj, string key, int defaultValue = 0)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return obj[key].ToInt32Value(defaultValue);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static long ToInt64(this IDictionary<string, object> obj, string key, long defaultValue = 0)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return obj[key].ToInt64Value(defaultValue);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static bool ToBoolean(this IDictionary<string, object> obj, string key, bool defaultValue = false)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return obj[key].ToBooleanValue(defaultValue);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static float ToFloat(this IDictionary<string, object> obj, string key, float defaultValue = 0.0f)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return obj[key].ToFloatValue(defaultValue);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static double ToDouble(this IDictionary<string, object> obj, string key, double defaultValue = 0.0d)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return obj[key].ToDoubleValue(defaultValue);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static DateTime? ToDateTime(this IDictionary<string, object> obj, string key, DateTime? defaultValue = null)
    {
      if (obj == null || key.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return obj[key].ToDateTimeValue(defaultValue);
    }

    /// <summary>
    /// 将IDictionary<TKey, TValue>转换成IDictionary对象
    /// </summary>
    /// <typeparam name="TKey">key的类型</typeparam>
    /// <typeparam name="TValue">value的类型</typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static IDictionary ToDictionary<TKey, TValue>(this IDictionary<TKey, TValue> obj)
    {
      var result = new Hashtable();
      var source = (obj as IDictionary<string, object>);
      foreach (var item in source)
      {
        result[item.Key] = item.Value;
      }
      return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="key"></param>
    /// <param name="defaultValueFunc"></param>
    /// <returns></returns>
    public static IList ToListValue(this IDictionary obj, object key, Func<IList> defaultValueFunc = null)
    {
      if (defaultValueFunc == null)
      {
        defaultValueFunc = () => new ArrayList();
      }
      if ((obj == null || key == null))
      {
        return null;
      }
      var resultList = obj.ToList(key);
      if (resultList == null)
      {
        var oldVal = obj[key];
        resultList = defaultValueFunc();
        if (oldVal != null)
        {
          resultList.Add(oldVal);
        }
        obj[key] = resultList;
      }
      return resultList;
    }

    #endregion IDictionary<string, object>扩展
  }
}
